MAF1731 - Microstructure and Trading Systems

María Fernanada Amador Alvarez

Gerardo González Flores

Ana Sofía Dürrmüller

Maximiliano García Mora

Marzo 2023 | Repository: Link

Módulo 5¶

Análisis Técnico

1. Introducción¶

El proyecto propuesto tiene como objetivo utilizar análisis técnico y herramientas financieras para generar oportunidades de trading en un par de divisas durante un período de entrenamiento y prueba. Se espera que el proyecto tenga la estructura básica de proyectos de Python y que se divida en tareas predefinidas para cada perfil. Además, se deben definir los cuatro criterios del sistema de trading y se debe realizar una optimización y backtest financiero del sistema utilizando parámetros específicos. El proyecto también incluirá aspectos estadísticos y computacionales, como la propuesta de estudios técnicos, la definición de una función de utilidad y parámetros a optimizar, el espacio de búsqueda y el método de optimización utilizado. Finalmente, se debe aplicar el sistema de trading a los datos de prueba y presentar los resultados a través de gráficas y tablas.

1.1 Objetivos:¶

Utilizar entre 2 y 4 estudios técnicos como herramientas para la generación de oportunidades de trading, lo que equivale a utilizar análisis técnico.

2. Paqueterías a utilizar¶

In [ ]:
import functions
import data
import visualizations
import plotly.io as pio

2. Archivos necesarios¶

  • AUSUSD_test
  • AUDUSD_train

3. Visualización¶

In [ ]:
# Train
train_df = data.data_open_2("AUDUSD_train.csv")
train_df
Out[ ]:
timeStamp Open High Low Close Mid
0 2020-01-01 0.701508 0.704500 0.701508 0.701700 0.701700
1 2020-01-02 0.701892 0.702100 0.698130 0.701951 0.701951
2 2020-01-03 0.698370 0.698661 0.693140 0.698519 0.698519
3 2020-01-06 0.694729 0.695900 0.692602 0.694420 0.694420
4 2020-01-07 0.693720 0.694100 0.686111 0.693731 0.693731
... ... ... ... ... ... ...
258 2020-12-28 0.761348 0.762400 0.755960 0.761191 0.761191
259 2020-12-29 0.758858 0.762500 0.758478 0.758892 0.758892
260 2020-12-30 0.761200 0.768622 0.760720 0.760990 0.760990
261 2020-12-31 0.768900 0.774140 0.768690 0.768929 0.768929
262 2021-01-01 0.777180 0.820760 0.769823 0.770297 0.770297

263 rows × 6 columns

In [ ]:
# Test
test_df = data.data_open_2("AUDUSD_test.csv")
test_df
Out[ ]:
timeStamp Open High Low Close Mid
0 2021-02-01 0.762062 0.766401 0.76135 0.761998 0.761998
1 2021-02-02 0.763330 0.766190 0.75667 0.763460 0.763460
2 2021-02-03 0.760900 0.762700 0.76024 0.760821 0.760821
3 2021-02-04 0.763633 0.764750 0.75900 0.763600 0.763600
4 2021-02-05 0.760092 0.766000 0.75844 0.760300 0.760300
... ... ... ... ... ... ...
257 2022-01-26 0.715880 0.717800 0.71508 0.715880 0.715880
258 2022-01-27 0.712140 0.712140 0.70421 0.712300 0.712300
259 2022-01-28 0.703700 0.704722 0.69686 0.703550 0.703550
260 2022-01-31 0.699428 0.707914 0.69932 0.699800 0.699800
261 2022-02-01 0.706590 0.711794 0.70347 0.706830 0.706830

262 rows × 6 columns

3.1 Datos y Validaciones¶

  1. Capital inicial: $100,000
  2. AUDUSD (Dólar Australiano vs. Dólar Estadounidense)
  3. Riesgo máximo por operación (pérdida máximo): $1,000 usd
  4. Datos divididos de la siguiente manera: Periodo de entrenamiento: 01/ene/2020 - 01/ene/2021 Periodo de prueba: 01/Feb/2021 - 01/Feb/2022
In [ ]:
# Train
train_df["timeStamp"].min(),train_df["timeStamp"].max()
Out[ ]:
('2020-01-01', '2021-01-01')
In [ ]:
# Test
test_df["timeStamp"].min(),test_df["timeStamp"].max()
Out[ ]:
('2021-02-01', '2022-02-01')

3.2 Aspectos Estadísticos¶

3.2.1 Estudios Técnicos¶

Se han implementado los siguientes 3 estudios técnicos para utilizarse como indicadores para la implementación de una estrategia de Trading:

Exponencial Moving Average (EMA)¶

El Exponential Moving Average (EMA) es un indicador técnico utilizado en análisis técnico de valores bursátiles para suavizar los datos de precios y mostrar la tendencia subyacente del precio de un activo. A diferencia del Simple Moving Average (SMA), el EMA da más peso a los precios más recientes, lo que lo convierte en un indicador más sensible a los cambios de precio más recientes.

La fórmula para el EMA es la siguiente:

$$ EMA(i) = (Precio(i) - EMA(i-1)) * (2 / (n + 1)) + EMA(i-1)$$

Donde:

  • $i$ es el índice de la fila actual en el dataframe.
  • $EMA(i)$ es el valor del EMA para la fila i.
  • $Precio(i)$ es el precio de cierre para la fila i.
  • $EMA(i-1)$ es el valor del EMA para la fila anterior.
  • $n$ es el número de períodos en el que se calcula el EMA. La fórmula se aplica iterativamente a cada fila del dataframe de precios para calcular el valor del EMA para esa fila. Para la primera fila, el valor del EMA es igual al precio de cierre. Para las filas siguientes, se utiliza el valor del EMA de la fila anterior en la fórmula para calcular el valor actual del EMA.

El valor de n en la fórmula del EMA es el número de períodos utilizados para calcular el EMA. Por ejemplo, si n es igual a 10, entonces el EMA se calcula utilizando los precios de cierre de los últimos 10 períodos. El valor de n puede ser ajustado por el analista técnico en función de sus preferencias y objetivos de análisis.

Parabolic SAR¶

El Parabolic SAR (Stop and Reverse) es un indicador técnico utilizado en análisis técnico de valores bursátiles para determinar el momento y la dirección del precio de un activo. La función del Parabolic SAR es identificar la tendencia del precio y proporcionar señales para comprar o vender el activo.

El SAR fue desarrollado por el analista técnico J. Welles Wilder y fue presentado en su libro "New Concepts in Technical Trading Systems" en 1978. Es una herramienta comúnmente utilizada por los traders y analistas técnicos para ayudar en la toma de decisiones de inversión. La fórmula para el valor del Parabolic SAR se calcula de acuerdo con la siguiente fórmula:

Si la tendencia es alcista: $$SAR(i) = SAR(i - 1) + AF(i - 1) * (EP(i - 1) - SAR(i - 1))$$ Si la tendencia es bajista: $$SAR(i) = SAR(i - 1) - AF(i - 1) * (SAR(i - 1) - EP(i - 1))$$

Donde:

  • $i$ es el índice de la fila actual en el dataframe.
  • $SAR(i)$ es el valor del Parabolic SAR para la fila i.
  • $SAR(i-1)$ es el valor del Parabolic SAR para la fila anterior.
  • $AF(i-1)$ es el factor de aceleración para la fila anterior.
  • $EP(i-1)$ es la tasa de cambio extrema para la fila anterior. La tasa de cambio extrema (EP, por sus siglas en inglés) es el precio más alto o más bajo observado durante la tendencia actual, según sea el caso. El factor de aceleración (AF, por sus siglas en inglés) es un valor que aumenta a medida que la tendencia continúa, lo que hace que el indicador sea más sensible a los cambios de precio. El valor inicial de AF se establece en un valor predeterminado, y luego aumenta en incrementos fijos a medida que la tendencia continúa, hasta alcanzar un valor máximo establecido por el analista técnico.

El valor inicial del Parabolic SAR se establece como el mínimo entre los precios mínimos de las dos primeras filas. Es decir:

$$SAR(1) = \min(Low(1), Low(2))$$

Donde Low(1) es el precio mínimo para la primera fila, y Low(2) es el precio mínimo para la segunda fila.

Aroon Oscillator¶

El Aroon Oscillator es un indicador técnico utilizado en análisis técnico de valores bursátiles para medir la fuerza de la tendencia y la probabilidad de que se produzca un cambio en la tendencia. Es una versión del indicador Aroon que se representa como un oscilador con valores que oscilan alrededor de una línea central de cero. El Aroon Oscillator puede tomar valores positivos o negativos. Los valores positivos indican que la tendencia alcista está ganando fuerza, mientras que los valores negativos indican que la tendencia bajista está ganando fuerza. Un valor de cero indica que no hay tendencia clara en el mercado.

La línea central de cero del Aroon Oscillator se utiliza como una señal para la toma de decisiones de inversión. Cuando el Aroon Oscillator cruza por encima de cero, se considera una señal de compra, y cuando cruza por debajo de cero, se considera una señal de venta.

Su fórmula es: $$Aroon Oscillator = Aroon Up - Aroon Down$$ Donde: $$Aroon Up = ((N - Periodo desde el último máximo) / N) * 100$$ $$Aroon Down = ((N - Periodo desde el último mínimo) / N) * 100$$ Donde:

  • N es el número total de períodos considerados en el cálculo del indicador.
  • Periodo desde el último máximo es el número de períodos desde el último máximo más alto hasta el período actual.
  • Periodo desde el último mínimo es el número de períodos desde el último mínimo más bajo hasta el período actual.
  • Aroon Up es el valor del indicador Aroon que mide la cantidad de períodos desde el último máximo más alto.
  • Aroon Down es el valor del indicador Aroon que mide la cantidad de períodos desde el último mínimo más bajo.
  • El valor de N en la fórmula es el número total de períodos considerados en el cálculo del indicador. Este valor se puede ajustar según las preferencias y objetivos del analista técnico.

El Aroon Up y el Aroon Down son indicadores separados que miden la cantidad de períodos desde el último máximo más alto y el último mínimo más bajo, respectivamente. Ambos indicadores varían entre 0 y 100, donde 100 indica que el máximo o el mínimo más reciente se alcanzó en el período actual, y 0 indica que no se alcanzó ningún máximo o mínimo en el período considerado.

El Aroon se utiliza comúnmente en análisis técnico para identificar la fuerza y la dirección de la tendencia en el mercado y para determinar cuándo se pueden producir cambios en la tendencia.

3.2.2 Estrategia de Entrada y Salida¶

La estrategia de trading utiliza los indicadores Parabolic SAR, Aroon Oscillator y EMA para tomar decisiones de compra y venta. Las reglas de entrada son las siguientes:

  • Si el precio de cierre es mayor que la EMA, el indicador Parabolic SAR está por debajo del precio y el Aroon Oscillator es positivo, se abre una posición larga (compra).
  • Si el precio de cierre es menor que la EMA, el indicador Parabolic SAR está por encima del precio y el Aroon Oscillator es negativo, se cierra la posición larga abierta previamente (venta). Las reglas de Stop Loss y Take Profit son las siguientes:

  • Si el capital diario alcanza un valor que representa una ganancia igual o superior al valor de take_profit_ratio del capital inicial, se activa la orden de Take Profit para cerrar la posición larga abierta.

  • Si el capital diario alcanza un valor que representa una pérdida igual o superior al valor de stop_loss_ratio del capital inicial, se activa la orden de Stop Loss para cerrar la posición larga abierta. La fórmula para entrar en una posición larga es la siguiente: $$Long_Entry = (Close > EMA) \& (ParabolicSAR < Close) \& (AroonOscillator > 0) \& (Position == 0)$$ La fórmula para salir de una posición larga es la siguiente: $$Exit = (Close < EMA) \& (ParabolicSAR > Close) \& (AroonOscillator < 0) \& (Position == 1)$$ Donde:

  • Close es el precio de cierre del activo.

  • EMA es la media móvil exponencial del precio.
  • Parabolic_SAR es el valor del Parabolic SAR.
  • Aroon_Oscillator es el valor del Aroon Oscillator.
  • Position es el estado de la posición (0 = no se tiene ninguna posición abierta, 1 = se tiene una posición larga abierta).
  • Long_Entry es una variable booleana que indica si se cumplieron las condiciones para abrir una posición larga.
  • Exit es una variable booleana que indica si se cumplieron las condiciones para cerrar una posición larga.

3.3 Aspectos Computacionales¶

3.3.1 Función de Utilidad¶

Se busca maximizar el retorno total de la estrategia de trading, variando el Take Profit, Stop Loss y tamaño de la operación

3.3.2 Parámetros a Optimizar¶

  • Parámetro 1
    • Nombre: Volumen o tamaño de la operación
    • Descripción: Volumen en unidades monetarias (dólares), con el que se abre la operación
    • Tipo de rango: Numérico
    • Rango de valores 100 - 10000
    • Tamaño de paso mínimo: 10
  • Parámetro 2
    • Nombre: Take Profit
    • Descripción: Dólares de ganancia con el cuál se cierra la operación
    • Tipo de rango: Numérico
    • Rango de valores 0 - Capital Total
    • Tamaño de paso mínimo: 1000
  • Parámetro 3
    • Nombre: Stop Loss
    • Descripción: Dólares de pérdida con los que se cierra la operación
    • Tipo de rango: Numérico
    • Rango de valores -Capital Total - 0
    • Tamaño de paso mínimo: 1000

3.3.3 Espacio de Búsqueda¶

  • Parámetro 1 (Volumen): Rango de valores (100 - 10000) / Tamaño de paso mínimo (10) + 1 = 991 valores posible.
  • Parámetro 2 (Take Profit): (0 - 100000) / 1000 + 1 = 101 valores posibles
  • Parámetro 3 (Stop Loss): (-100000 - 0) / 1000 + 1 = 101 valores posibles Entonces, el espacio total de búsqueda sería el producto de la cantidad de valores posibles para cada parámetro: Espacio de búsqueda = 991 (Volumen) 101 (Take Profit) 101 (Stop Loss) = 10,181,391 valores posibles

Esto significa que hay 10,181,391 posibles combinaciones de los valores de estos tres parámetros en el espacio de búsqueda.

3.3.4 Tiempo de búsqueda exhaustiva¶

Asignando 0.5 segundos de tiempo transcurrido para cada vez que corres el código con una configuración de parámetros, dadas 10,181,391 posibles combinaciones, el tiempo es de:

Tiempo de búsqueda exhaustiva = 5,090,695.5 segundos

El tiempo de búsqueda exhaustiva para el óptimo de los 10,181,391 combinaciones posibles sería aproximadamente 59 días.

3.3.5 Método de optimización¶

El método 'L-BFGS-B' es un algoritmo de optimización que pertenece a la familia de métodos cuasi-Newtonianos. 'L-BFGS-B' es la versión limitada del algoritmo 'BFGS' (Broyden-Fletcher-Goldfarb-Shanno) que admite restricciones de límites en los parámetros de optimización.

El algoritmo 'BFGS' es un método iterativo que utiliza una aproximación de la matriz de Hesse inversa para calcular la dirección de búsqueda. La versión 'L-BFGS' (Limited-memory BFGS) es una variante que utiliza una cantidad limitada de memoria, lo que la hace más adecuada para problemas de optimización con un gran número de variables.

El algoritmo 'L-BFGS-B' combina las ventajas del algoritmo 'L-BFGS' con la capacidad de manejar restricciones de límites en los parámetros de optimización. Esto es útil en situaciones donde se necesita restringir los valores de los parámetros a un rango específico.

4. Ejecución de la estrategia¶

In [ ]:
# Preprocesamiento de dataframes para evaluación de estrategia
# Creación de indicadores
# Exponential Moving Average y Aroon Oscillator
train_df = (
    train_df.pipe(functions.calculate_ema, 20)
            .pipe(functions.calculate_aroon_oscillator)
)
# Parabolic SAR
train_df["Parabolic_SAR"] = functions.calculate_parabolic_sar(train_df)
# Exponential Moving Average y Aroon Oscillator
test_df = (
    test_df.pipe(functions.calculate_ema, 20)
            .pipe(functions.calculate_aroon_oscillator)
)
# Parabolic SAR
test_df["Parabolic_SAR"] = functions.calculate_parabolic_sar(test_df)

# Optimización de parámetros y Backtesting (sólo sobre Train se realiza)
best_params_train,iter_val_test = functions.best_fit_params(train_df)
print("Best take_profit_ratio:", best_params_train[0])
print("Best stop_loss_ratio:", best_params_train[1])
print("Best position_size:", best_params_train[2])

# Creación del portafolio a partir de la estrategia con parámetros optimizados
# Backtesting sobre entrenamiento
portfolio = functions.run_trading_strategy(train_df,
                                             capital=100000,
                                             take_profit_ratio=best_params_train[0],
                                             stop_loss_ratio=best_params_train[1],
                                             position_size=best_params_train[2])
# Sobre datos de prueba
portfolio_test = functions.run_trading_strategy(test_df,
                                             capital=100000,
                                             take_profit_ratio=best_params_train[0],
                                             stop_loss_ratio=best_params_train[1],
                                             position_size=best_params_train[2])

# Métricas de atribución al desempeño
MAD_train = functions.portfolio_metrics(portfolio[["timeStamp",
                                                  "Long_Entry","Exit","Position",
                                                  "Capital","Daily_Profit",
                                                  "Take_Profit","Stop_Loss","Returns",
                                                  "Cumulative_Returns"]])
MAD_test = functions.portfolio_metrics(portfolio_test[["timeStamp",
                                                  "Long_Entry","Exit","Position",
                                                  "Capital","Daily_Profit",
                                                  "Take_Profit","Stop_Loss","Returns",
                                                  "Cumulative_Returns"]])

# Visualizaciones
# Visualización de indicadores calculados sobre las series de tiempo
# Se tienen que realizar sobre el slice de la posición 1 hacia adelante porque el Aroon en 0 es 0 y hace
# que la gráfica salga espantosa
train_ind = visualizations.plot_indicators(train_df.iloc[1:,:])
test_ind = visualizations.plot_indicators(test_df.iloc[1:,:])
# Visualización de la estrategia sobre la serie de tiempo
trading_strat_train = visualizations.plot_indicators_2(portfolio.iloc[1:,:])
trading_strat_test = visualizations.plot_indicators_2(portfolio_test.iloc[1:,:])
#Visualización de la convergencia en la optimización de la estrategia
conv_graph = visualizations.plot_capital_evolution(iter_val_test)
Best take_profit_ratio: 0.01
Best stop_loss_ratio: 0.01
Best position_size: 10000.0

5. Resultados¶

5.1 Indicadores técnicos¶

In [ ]:
g_train = train_ind.show(renderer = 'notebook')
g_train
In [ ]:
g_test = test_ind.show(renderer = 'notebook')
g_test

5.1.1 Validación gráfica de la estrategia¶

Cada línea verde es una entrada de la estrategia, cada línea roja, una salida de acuerdo a las reglas de salida y las reglas de take profit y stop loss

In [ ]:
g_ttrain = trading_strat_train.show(renderer = 'notebook')
g_ttrain
In [ ]:
gttest = trading_strat_test.show(renderer = 'notebook')
gttest

5.2 Métricas de Atribución al Desempeño¶

In [ ]:
MAD_train
Out[ ]:
Total_Return Average_Return Volatility Sharpe_Ratio
0 2.120347 0.038695 0.787431 -6.30062
In [ ]:
MAD_test
Out[ ]:
Total_Return Average_Return Volatility Sharpe_Ratio
0 0.231515 -0.027313 0.544409 -9.234434

5.3 Gráfica de Convergencia de la optimización¶

In [ ]:
g_conv = conv_graph.show(renderer = 'notebook')
g_conv

6. Conclusiones¶

Como equipo, hemos trabajado arduamente para diseñar y ejecutar cada tarea del proyecto, siguiendo la estructura básica de proyectos de Python y dividiendo las tareas predefinidas para cada perfil de manera equitativa y efectiva. La estrategia de trading fue capaz de generar un rendimiento positivo, sin embargo no fue capaz de superar a la tasa libre de riesgo establecida del 5%, dando como resultado un radio de sharpe negativo.

Para asegurarnos de que el sistema de trading propuesto sea efectivo, definimos los cuatro criterios necesarios para su éxito y realizamos una optimización y backtest financiero utilizando parámetros específicos. A través de estudios técnicos, definimos una función de utilidad y los parámetros que debían optimizarse, junto con el espacio de búsqueda y el método de optimización utilizado.

En el proceso, también consideramos los aspectos estadísticos y computacionales necesarios para garantizar la precisión de los resultados. Hemos trabajado en equipo para asegurarnos de que todos los aspectos del proyecto estén integrados y funcionando sin problemas.

Finalmente, aplicamos el sistema de trading a los datos de prueba y presentamos los resultados a través de gráficas y tablas. A través de nuestro esfuerzo conjunto y nuestro enfoque riguroso, hemos logrado desarrollar un sistema de trading sólido y eficaz, que esperamos que tenga un gran impacto en el mundo financiero.

Hemos aprendido mucho sobre análisis técnico, herramientas financieras y estrategias de trading, así como sobre la importancia de trabajar en equipo y mantener altos estándares de calidad en nuestros proyectos.

7. Referencias¶

  • Klinker, F. (2011). Exponential moving average versus moving exponential average. Mathematische Semesterberichte, 58, 97-107.
  • Yazdi, S. H. M., & LASHKARI, Z. H. (2012, November). Technical analysis of Forex by Parabolic SAR Indicator. In International Islamic Accounting and Finance Conference.